<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>🐒 锁 | Xiangyu&#39;s Blog</title>
    <meta name="generator" content="VuePress 1.8.2">
    <script src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone/babel.min.js"></script>
    <link rel="alternate" type="application/atom+xml" href="https://blog.lixiangyu.xyz/atom.xml" title="Xiangyu&#39;s Blog Atom Feed">
    <link rel="alternate" type="application/json" href="https://blog.lixiangyu.xyz/feed.json" title="Xiangyu&#39;s Blog JSON Feed">
    <link rel="alternate" type="application/rss+xml" href="https://blog.lixiangyu.xyz/rss.xml" title="Xiangyu&#39;s Blog RSS Feed">
    <meta name="description" content="">
    <meta property="og:url" content="/interview/java-multithread/lock.html">
    <meta property="og:site_name" content="Xiangyu's Blog">
    <meta property="og:title" content="🐒 锁">
    <meta property="og:type" content="article">
    <meta property="og:locale" content="zh-CN">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:image:alt" content="Xiangyu's Blog">
    <meta property="article:author" content="Xiangyu Li">
    
    <link rel="preload" href="/assets/css/0.styles.79654418.css" as="style"><link rel="preload" href="/assets/js/app.a42375e9.js" as="script"><link rel="preload" href="/assets/js/vendors~layout-Layout.8269724e.js" as="script"><link rel="preload" href="/assets/js/vendors~layout-Blog~layout-Layout~layout-NotFound.43b0f70d.js" as="script"><link rel="preload" href="/assets/js/page-🐒锁.868714d5.js" as="script"><link rel="preload" href="/assets/js/vendors~layout-Blog~layout-Layout~layout-NotFound~layout-Slide.99c28334.js" as="script"><link rel="prefetch" href="/assets/js/120.3fbfaa84.js"><link rel="prefetch" href="/assets/js/121.1b7d4f7b.js"><link rel="prefetch" href="/assets/js/122.beff33c9.js"><link rel="prefetch" href="/assets/js/123.b1ea2b2a.js"><link rel="prefetch" href="/assets/js/124.80db1ca6.js"><link rel="prefetch" href="/assets/js/layout-Blog.5897b816.js"><link rel="prefetch" href="/assets/js/layout-Layout.62afd99c.js"><link rel="prefetch" href="/assets/js/layout-NotFound.232bd0de.js"><link rel="prefetch" href="/assets/js/layout-Slide.3e86b53c.js"><link rel="prefetch" href="/assets/js/mermaid.efa5ef99.js"><link rel="prefetch" href="/assets/js/page-☀️类加载机制.e96f671b.js"><link rel="prefetch" href="/assets/js/page-☘️通讯组件-简介.4b81f185.js"><link rel="prefetch" href="/assets/js/page-♟️百度.c4749d47.js"><link rel="prefetch" href="/assets/js/page-⛈️Map接口-简介.3865d2e3.js"><link rel="prefetch" href="/assets/js/page-⛑️HTTPS协议.66168577.js"><link rel="prefetch" href="/assets/js/page-⛷️TreeSet.9d82d551.js"><link rel="prefetch" href="/assets/js/page-⛹️LinkedHashMap.a11fa0e5.js"><link rel="prefetch" href="/assets/js/page-✈️Kafka.02647d0b.js"><link rel="prefetch" href="/assets/js/page-✌️索引.8092b72a.js"><link rel="prefetch" href="/assets/js/page-⭐内存区域划分.b3f4a65e.js"><link rel="prefetch" href="/assets/js/page-主页.28a585f2.js"><link rel="prefetch" href="/assets/js/page-🌀JVM-简介.cbd691d7.js"><link rel="prefetch" href="/assets/js/page-🌀JavaIO-简介.8b218ef6.js"><link rel="prefetch" href="/assets/js/page-🌀Java基础-简介.3cff2536.js"><link rel="prefetch" href="/assets/js/page-🌀Java容器-简介.21a7bf8b.js"><link rel="prefetch" href="/assets/js/page-🌀Java并发-简介.a400b8d1.js"><link rel="prefetch" href="/assets/js/page-🌀MySQL-简介.61b33b6a.js"><link rel="prefetch" href="/assets/js/page-🌀Redis-简介.f815bad6.js"><link rel="prefetch" href="/assets/js/page-🌀中间件-简介.5640181c.js"><link rel="prefetch" href="/assets/js/page-🌀操作系统-简介.46e7356e.js"><link rel="prefetch" href="/assets/js/page-🌀框架使用-简介.3af4c120.js"><link rel="prefetch" href="/assets/js/page-🌀计算机网络-简介.23bd59fd.js"><link rel="prefetch" href="/assets/js/page-🌀设计思想-简介.0711e244.js"><link rel="prefetch" href="/assets/js/page-🌀面经.5cfe0142.js"><link rel="prefetch" href="/assets/js/page-🌙垃圾回收机制.db23d79a.js"><link rel="prefetch" href="/assets/js/page-🌧️Set接口-简介.d19cf767.js"><link rel="prefetch" href="/assets/js/page-🌩️List接口-简介.112f20b7.js"><link rel="prefetch" href="/assets/js/page-🌲Spring.bc450c2f.js"><link rel="prefetch" href="/assets/js/page-🌳SpringMVC.91b7e35a.js"><link rel="prefetch" href="/assets/js/page-🌴SpringBoot.ff4435cc.js"><link rel="prefetch" href="/assets/js/page-🌵SpringCloud.61f20500.js"><link rel="prefetch" href="/assets/js/page-🌻MyBatis.2d99e7fc.js"><link rel="prefetch" href="/assets/js/page-🌼MyBatis框架-简介.66f9a744.js"><link rel="prefetch" href="/assets/js/page-🍀Netty.54e2d65a.js"><link rel="prefetch" href="/assets/js/page-🍁Dubbo.66727d8a.js"><link rel="prefetch" href="/assets/js/page-🎧学堂在线.81d9ee7e.js"><link rel="prefetch" href="/assets/js/page-🎭Boss直聘.14beba08.js"><link rel="prefetch" href="/assets/js/page-🎱老虎集团.fc8b12ba.js"><link rel="prefetch" href="/assets/js/page-🎲字节跳动.5676ea28.js"><link rel="prefetch" href="/assets/js/page-🎺猿辅导.7520f1e7.js"><link rel="prefetch" href="/assets/js/page-🏄LinkedHashSet.2e22c9f1.js"><link rel="prefetch" href="/assets/js/page-🏌️HashSet.820baa69.js"><link rel="prefetch" href="/assets/js/page-🐵JUC.9672a0f1.js"><link rel="prefetch" href="/assets/js/page-👂视图.f277e783.js"><link rel="prefetch" href="/assets/js/page-👋数据类型.b99f167f.js"><link rel="prefetch" href="/assets/js/page-👍事务.ef00d241.js"><link rel="prefetch" href="/assets/js/page-👎慢查询.a1afcd91.js"><link rel="prefetch" href="/assets/js/page-👓IP地址.f0579df2.js"><link rel="prefetch" href="/assets/js/page-👕其他.647a9b2f.js"><link rel="prefetch" href="/assets/js/page-👟滑动窗口.b3cb4c10.js"><link rel="prefetch" href="/assets/js/page-👣IP协议基础.c423881a.js"><link rel="prefetch" href="/assets/js/page-👨‍💼TCP协议-简介.8dad7177.js"><link rel="prefetch" href="/assets/js/page-👨‍🔧IP-简介.45549536.js"><link rel="prefetch" href="/assets/js/page-👨‍🔧设计模式.2b288cfc.js"><link rel="prefetch" href="/assets/js/page-💁‍♂️Redis事务.2da37f16.js"><link rel="prefetch" href="/assets/js/page-💂面试知识点整理.53653cc8.js"><link rel="prefetch" href="/assets/js/page-💍HTTP协议的改进.9d91d303.js"><link rel="prefetch" href="/assets/js/page-💐Spring全家桶-简介.bc0ceb52.js"><link rel="prefetch" href="/assets/js/page-💼HTTP协议的请求方法.49ea5b30.js"><link rel="prefetch" href="/assets/js/page-🖐️存储引擎.51e90aae.js"><link rel="prefetch" href="/assets/js/page-🖖DDL.58e99d50.js"><link rel="prefetch" href="/assets/js/page-😀面向对象的特点.64db987a.js"><link rel="prefetch" href="/assets/js/page-😁Object类.bd3dee32.js"><link rel="prefetch" href="/assets/js/page-😆String类.6fe32326.js"><link rel="prefetch" href="/assets/js/page-😎泛型.9245d81a.js"><link rel="prefetch" href="/assets/js/page-😛关键字.1e781f13.js"><link rel="prefetch" href="/assets/js/page-😪反射.ef7a385f.js"><link rel="prefetch" href="/assets/js/page-😵异常.6c2ba11a.js"><link rel="prefetch" href="/assets/js/page-🙅‍♂️Redis淘汰策略.650f7bea.js"><link rel="prefetch" href="/assets/js/page-🙆‍♂️Redis持久化策略.d130b1b1.js"><link rel="prefetch" href="/assets/js/page-🙇‍♂️Redis基础.2c3c39e8.js"><link rel="prefetch" href="/assets/js/page-🙈JMM.3512b22b.js"><link rel="prefetch" href="/assets/js/page-🙉进程和线程.f7aa9975.js"><link rel="prefetch" href="/assets/js/page-🙊线程池.bab2c4d8.js"><link rel="prefetch" href="/assets/js/page-🙋‍♂️Redis底层实现.7416ea6f.js"><link rel="prefetch" href="/assets/js/page-🚥ZooKeeper.57458d21.js"><link rel="prefetch" href="/assets/js/page-🚵HashTable.ccce702b.js"><link rel="prefetch" href="/assets/js/page-🚶‍♂️超时重传机制.cfb21e2f.js"><link rel="prefetch" href="/assets/js/page-🤚范式.b6a8d503.js"><link rel="prefetch" href="/assets/js/page-🤝集群.bdd1180d.js"><link rel="prefetch" href="/assets/js/page-🤞锁.c12200cd.js"><link rel="prefetch" href="/assets/js/page-🤦‍♂️故障处理.80248294.js"><link rel="prefetch" href="/assets/js/page-🤪包装类和缓存池.4fa40654.js"><link rel="prefetch" href="/assets/js/page-🤴HTTP协议-简介.c55283d9.js"><link rel="prefetch" href="/assets/js/page-🤸ArrayList.f0cf8991.js"><link rel="prefetch" href="/assets/js/page-🤹LinkedList.caf8cd71.js"><link rel="prefetch" href="/assets/js/page-🤼HashMap.2ad7d223.js"><link rel="prefetch" href="/assets/js/page-🤾Vector.7740cb05.js"><link rel="prefetch" href="/assets/js/page-🥁好大夫在线.e46779d8.js"><link rel="prefetch" href="/assets/js/page-🦍无同步方案.9b8df198.js"><link rel="prefetch" href="/assets/js/page-🧏‍♂️Redis集群.6d3441ab.js"><link rel="prefetch" href="/assets/js/page-🧐其他.deb18f3f.js"><link rel="prefetch" href="/assets/js/page-🧘ConcurrentHashMap.a3e51c7d.js"><link rel="prefetch" href="/assets/js/page-🧙‍♂️内存管理.c1b418f2.js"><link rel="prefetch" href="/assets/js/page-🧚CPU缓存一致性.8647e92e.js"><link rel="prefetch" href="/assets/js/page-🧛‍♂️IO.3bf30d07.js"><link rel="prefetch" href="/assets/js/page-🧝‍♂️进程与线程.f1df829e.js"><link rel="prefetch" href="/assets/js/page-🧟锁.86b4ff29.js"><link rel="prefetch" href="/assets/js/page-🧣TCP协议基础.2e717ff6.js"><link rel="prefetch" href="/assets/js/page-🧤拥塞控制.9018c6ff.js"><link rel="prefetch" href="/assets/js/page-🧥HTTP协议基础.719b302d.js"><link rel="prefetch" href="/assets/js/page-🧩美团.7049187d.js"><link rel="prefetch" href="/assets/js/page-🧳建立与释放连接.b95bfaf5.js"><link rel="prefetch" href="/assets/js/page-🧶元保数科.aba682de.js"><link rel="prefetch" href="/assets/js/vendors~flowchart.846214db.js"><link rel="prefetch" href="/assets/js/vendors~mermaid.4a0cbbd3.js"><link rel="prefetch" href="/assets/js/vendors~photo-swipe.515ad438.js"><link rel="prefetch" href="/assets/js/vendors~reveal.b4fb0aa4.js"><link rel="prefetch" href="/assets/js/vendors~waline.c2d7e472.js">
    <link rel="stylesheet" href="/assets/css/0.styles.79654418.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container has-navbar has-sidebar has-anchor"><header class="navbar"><!----> <div class="content__navbar-start"></div> <button title="Sidebar Button" class="sidebar-button"><span class="icon"></span></button> <a href="/" class="home-link router-link-active"><img src="/icon.png" alt="Xiangyu's Blog" class="logo"> <!----> <span class="site-name can-hide">Xiangyu's Blog</span></a> <!----> <div class="content__navbar-center"></div> <div class="links"><button aria-hidden="true" class="color-button"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="skin-icon"><path d="M224 800c0 9.6 3.2 44.8 6.4 54.4 6.4 48-48 76.8-48 76.8s80 41.6 147.2 0 134.4-134.4
        38.4-195.2c-22.4-12.8-41.6-19.2-57.6-19.2C259.2 716.8 227.2 761.6 224 800zM560 675.2l-32
        51.2c-51.2 51.2-83.2 32-83.2 32 25.6 67.2 0 112-12.8 128 25.6 6.4 51.2 9.6 80 9.6 54.4 0
        102.4-9.6 150.4-32l0 0c3.2 0 3.2-3.2 3.2-3.2 22.4-16 12.8-35.2
        6.4-44.8-9.6-12.8-12.8-25.6-12.8-41.6 0-54.4 60.8-99.2 137.6-99.2 6.4 0 12.8 0 22.4
        0 12.8 0 38.4 9.6 48-25.6 0-3.2 0-3.2 3.2-6.4 0-3.2 3.2-6.4 3.2-6.4 6.4-16 6.4-16 6.4-19.2
        9.6-35.2 16-73.6 16-115.2 0-105.6-41.6-198.4-108.8-268.8C704 396.8 560 675.2 560 675.2zM224
        419.2c0-28.8 22.4-51.2 51.2-51.2 28.8 0 51.2 22.4 51.2 51.2 0 28.8-22.4 51.2-51.2 51.2C246.4
        470.4 224 448 224 419.2zM320 284.8c0-22.4 19.2-41.6 41.6-41.6 22.4 0 41.6 19.2 41.6 41.6 0
        22.4-19.2 41.6-41.6 41.6C339.2 326.4 320 307.2 320 284.8zM457.6 208c0-12.8 12.8-25.6 25.6-25.6
        12.8 0 25.6 12.8 25.6 25.6 0 12.8-12.8 25.6-25.6 25.6C470.4 233.6 457.6 220.8 457.6 208zM128
        505.6C128 592 153.6 672 201.6 736c28.8-60.8 112-60.8 124.8-60.8-16-51.2 16-99.2
        16-99.2l316.8-422.4c-48-19.2-99.2-32-150.4-32C297.6 118.4 128 291.2 128 505.6zM764.8
        86.4c-22.4 19.2-390.4 518.4-390.4 518.4-22.4 28.8-12.8 76.8 22.4 99.2l9.6 6.4c35.2 22.4
        80 12.8 99.2-25.6 0 0 6.4-12.8 9.6-19.2 54.4-105.6 275.2-524.8 288-553.6
        6.4-19.2-3.2-32-19.2-32C777.6 76.8 771.2 80 764.8 86.4z"></path></svg> <div class="color-picker-menu" style="display:none;"><div class="theme-options"><ul class="themecolor-select"><label for="themecolor-select">主题色:</label> <li><span class="default-theme"></span></li> </ul> <div class="darkmode-toggle"><label for="darkmode-toggle" class="desc">主题模式:</label> <div class="darkmode-switch"><div class="item day"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon light-icon"><path d="M512 256a42.667 42.667 0 0 0 42.667-42.667V128a42.667 42.667 0 0 0-85.334 0v85.333A42.667 42.667 0 0 0 512 256zm384 213.333h-85.333a42.667 42.667 0 0 0 0 85.334H896a42.667 42.667 0 0 0 0-85.334zM256 512a42.667 42.667 0 0 0-42.667-42.667H128a42.667 42.667 0 0 0 0 85.334h85.333A42.667 42.667 0 0 0 256 512zm9.387-298.667a42.667 42.667 0 0 0-59.307 62.72l61.44 59.307a42.667 42.667 0 0 0 31.147 11.947 42.667 42.667 0 0 0 30.72-13.227 42.667 42.667 0 0 0 0-60.16zm459.946 133.974a42.667 42.667 0 0 0 29.44-11.947l61.44-59.307a42.667 42.667 0 0 0-57.6-62.72l-61.44 60.587a42.667 42.667 0 0 0 0 60.16 42.667 42.667 0 0 0 28.16 13.227zM512 768a42.667 42.667 0 0 0-42.667 42.667V896a42.667 42.667 0 0 0 85.334 0v-85.333A42.667 42.667 0 0 0 512 768zm244.48-79.36a42.667 42.667 0 0 0-59.307 61.44l61.44 60.587a42.667 42.667 0 0 0 29.44 11.946 42.667 42.667 0 0 0 30.72-12.8 42.667 42.667 0 0 0 0-60.586zm-488.96 0-61.44 59.307a42.667 42.667 0 0 0 0 60.586 42.667 42.667 0 0 0 30.72 12.8 42.667 42.667 0 0 0 28.587-10.666l61.44-59.307a42.667 42.667 0 0 0-59.307-61.44zM512 341.333A170.667 170.667 0 1 0 682.667 512 170.667 170.667 0 0 0 512 341.333z" fill="currentColor"></path></svg></div> <div class="item auto active"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon auto-icon"><path d="M460.864 539.072H564.8L510.592 376l-49.728 163.072zM872 362.368V149.504H659.648L510.528 0l-149.12 149.504H149.12v212.928L0 511.872l149.12 149.504v212.928h212.352l149.12 149.504 149.12-149.504h212.352V661.376l149.12-149.504L872 362.368zM614.464 693.12l-31.616-90.624H438.272l-31.616 90.624h-85.888l144.576-407.68h90.368l144.576 407.68h-85.824zm0 0" fill="currentColor"></path></svg></div> <div class="item night"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon dark-icon"><path d="M935.539 630.402c-11.43-11.432-28.674-14.739-43.531-8.354-46.734 20.103-96.363 30.297-147.508 30.297-99.59 0-193.221-38.784-263.64-109.203-108.637-108.637-139.61-270.022-78.908-411.148a39.497 39.497 0 0 0-51.886-51.887c-52.637 22.64-100.017 54.81-140.826 95.616-85.346 85.346-132.346 198.821-132.346 319.52 0 120.7 47.001 234.172 132.347 319.519S408.063 947.11 528.76 947.11c120.7 0 234.172-47.003 319.52-132.351 40.809-40.81 72.978-88.19 95.616-140.826a39.497 39.497 0 0 0-8.356-43.532z" fill="currentColor"></path></svg></div></div> <!----></div></div></div></button> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link router-link-active"><i class="iconfont icon-home"></i>
  主页
</a></div><div class="nav-item"><a href="/interview/" class="nav-link router-link-active active"><i class="iconfont icon-launch"></i>
  面试题整理
</a></div></nav> <!----> <a rel="noopener noreferrer" href="https://github.com/lxy1152/lxy1152.github.io" target="_blank" class="repo-link can-hide">
  GitHub
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> <!----> <div class="content__navbar-end"></div></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><!----> <!----> <div class="content__sidebar-top"></div> <nav class="sidebar-nav-links"><div class="nav-item"><a href="/" class="nav-link router-link-active"><i class="iconfont icon-home"></i>
  主页
</a></div><div class="nav-item"><a href="/interview/" class="nav-link router-link-active active"><i class="iconfont icon-launch"></i>
  面试题整理
</a></div> <a rel="noopener noreferrer" href="https://github.com/lxy1152/lxy1152.github.io" target="_blank" class="repo-link">
  GitHub
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <!----> <div class="content__sidebar-center"></div> <ul class="sidebar-links"><li><a href="/interview/" aria-current="page" class="sidebar-link">💂 面试知识点整理</a></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">😉 Java 基础</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🌈 Java 容器</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable open"><!----> <span class="title">🐺 Java 并发</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/interview/java-multithread/" aria-current="page" class="sidebar-link">🌀 Java 并发 - 简介</a></li><li><a href="/interview/java-multithread/jmm/" class="sidebar-link">🙈 JMM</a></li><li><a href="/interview/java-multithread/process-thread/" class="sidebar-link">🙉 进程和线程</a></li><li><a href="/interview/java-multithread/thread-pool/" class="sidebar-link">🙊 线程池</a></li><li><a href="/interview/java-multithread/juc/" class="sidebar-link">🐵 J.U.C</a></li><li><a href="/interview/java-multithread/lock/" aria-current="page" class="active sidebar-link">🐒 锁</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#什么是互斥同步" class="sidebar-link">什么是互斥同步？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#介绍一下-synchronized-关键字" class="sidebar-link">介绍一下 Synchronized 关键字？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#介绍一下-reentrantlock-类" class="sidebar-link">介绍一下 ReentrantLock 类？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#它们两个有什么区别" class="sidebar-link">它们两个有什么区别？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#什么是非阻塞同步" class="sidebar-link">什么是非阻塞同步？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#什么是-cas" class="sidebar-link">什么是 CAS？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#cas-存在的问题" class="sidebar-link">CAS 存在的问题？</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#aba-问题" class="sidebar-link heading3">ABA 问题</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#自旋消耗资源" class="sidebar-link heading3">自旋消耗资源</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#多变量共享一致性问题" class="sidebar-link heading3">多变量共享一致性问题</a></li></ul></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#介绍一下-atomicinteger-类" class="sidebar-link">介绍一下 AtomicInteger 类？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#锁优化" class="sidebar-link">锁优化</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#什么是自旋锁" class="sidebar-link heading3">什么是自旋锁？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#什么是锁消除" class="sidebar-link heading3">什么是锁消除？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#什么是锁粗化" class="sidebar-link heading3">什么是锁粗化？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#什么是轻量级锁" class="sidebar-link heading3">什么是轻量级锁？</a></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#什么是偏向锁" class="sidebar-link heading3">什么是偏向锁？</a></li></ul></li><li class="sidebar-sub-header"><a href="/interview/java-multithread/lock/#在-java-中怎么排查死锁" class="sidebar-link">在 Java 中怎么排查死锁？</a></li></ul></li><li><a href="/interview/java-multithread/non-lock/" class="sidebar-link">🦍 无同步方案</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">⛳ Java I/O</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🌏 JVM</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🌱 框架使用</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">👊 MySQL</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🤷‍♂️ Redis</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🎠 中间件</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">👨‍👧‍👧 计算机网络</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🦸 操作系统</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🏭 设计思想</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">📚 面经</span> <span class="arrow right"></span></p> <!----></section></li></ul> <!----> <div class="content__sidebar-bottom"></div> <!----></aside> <main class="page"><nav class="breadcrumb"><ol vocab="https://schema.org/" typeof="BreadcrumbList"><li property="itemListElement" typeof="ListItem"><a href="/interview/" property="item" typeof="WebPage" class="router-link-active"><!----> <span property="name">💂 面试知识点整理</span></a> <meta property="position" content="1"></li><li property="itemListElement" typeof="ListItem"><a href="/interview/java-multithread/" property="item" typeof="WebPage" class="router-link-active"><!----> <span property="name">🌀 Java 并发 - 简介</span></a> <meta property="position" content="2"></li><li property="itemListElement" typeof="ListItem" class="is-active"><a href="/interview/java-multithread/lock/" aria-current="page" property="item" typeof="WebPage" class="router-link-exact-active router-link-active"><!----> <span property="name">🐒 锁</span></a> <meta property="position" content="3"></li></ol></nav> <!----> <div class="content__page-top"></div> <div vocab="https://schema.org/" typeof="Article" class="page-title"><h1><!----> <span property="headline">🐒 锁</span></h1> <div class="page-info"><!----> <span aria-label="作者🖊" data-balloon-pos="down"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon author-icon"><path d="M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z" fill="currentColor"></path></svg> <span property="author">Xiangyu Li</span></span><span aria-label="访问量🔢" data-balloon-pos="down" class="visitor-info"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon eye-icon"><path d="M992 512.096c0-5.76-.992-10.592-1.28-11.136-.192-2.88-1.152-8.064-2.08-10.816-.256-.672-.544-1.376-.832-2.08-.48-1.568-1.024-3.104-1.6-4.32C897.664 290.112 707.104 160 512 160c-195.072 0-385.632 130.016-473.76 322.592-1.056 2.112-1.792 4.096-2.272 5.856a55.512 55.512 0 0 0-.64 1.6c-1.76 5.088-1.792 8.64-1.632 7.744-.832 3.744-1.568 11.168-1.568 11.168-.224 2.272-.224 4.032.032 6.304 0 0 .736 6.464 1.088 7.808.128 1.824.576 4.512 1.12 6.976h-.032c.448 2.08 1.12 4.096 1.984 6.08.48 1.536.992 2.976 1.472 4.032C126.432 733.856 316.992 864 512 864c195.136 0 385.696-130.048 473.216-321.696 1.376-2.496 2.24-4.832 2.848-6.912.256-.608.48-1.184.672-1.728 1.536-4.48 1.856-8.32 1.728-8.32l-.032.032c.608-3.104 1.568-7.744 1.568-13.28zM512 672c-88.224 0-160-71.776-160-160s71.776-160 160-160 160 71.776 160 160-71.776 160-160 160z" fill="currentColor"></path></svg> <span id="/interview/java-multithread/lock/" data-flag-title="🐒 锁" class="leancloud_visitors"><span class="leancloud-visitors-count">...</span></span></span><span aria-label="写作日期📅" data-balloon-pos="down" class="time-info"><svg viewBox="0 0 1030 1024" xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 0 1-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 0 1-33.473-33.473V143.657H180.6A134.314 134.314 0 0 0 46.66 277.595v535.756A134.314 134.314 0 0 0 180.6 947.289h669.74a134.36 134.36 0 0 0 133.94-133.938V277.595a134.314 134.314 0 0 0-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 0 1-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 0 1-33.472 33.473z" fill="currentColor"></path></svg> <span property="datePublished">2021-8-1</span></span><!----><!----><span aria-label="阅读时间⌛" data-balloon-pos="down" class="reading-time-info"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon timer-icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z" fill="currentColor"></path></svg> <span>大约 10 分钟</span> <meta property="timeRequired" content="PT10M"></span></div> <!----> <hr></div> <div class="anchor-place-holder"><aside id="anchor"><div class="anchor-wrapper"><ul class="anchor-list"><li class="anchor"><a href="/interview/java-multithread/lock/#什么是互斥同步" class="anchor-link heading2"><div>什么是互斥同步？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#介绍一下-synchronized-关键字" class="anchor-link heading2"><div>介绍一下 Synchronized 关键字？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#介绍一下-reentrantlock-类" class="anchor-link heading2"><div>介绍一下 ReentrantLock 类？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#它们两个有什么区别" class="anchor-link heading2"><div>它们两个有什么区别？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#什么是非阻塞同步" class="anchor-link heading2"><div>什么是非阻塞同步？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#什么是-cas" class="anchor-link heading2"><div>什么是 CAS？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#cas-存在的问题" class="anchor-link heading2"><div>CAS 存在的问题？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#aba-问题" class="anchor-link heading3"><div>ABA 问题</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#自旋消耗资源" class="anchor-link heading3"><div>自旋消耗资源</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#多变量共享一致性问题" class="anchor-link heading3"><div>多变量共享一致性问题</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#介绍一下-atomicinteger-类" class="anchor-link heading2"><div>介绍一下 AtomicInteger 类？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#锁优化" class="anchor-link heading2"><div>锁优化</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#什么是自旋锁" class="anchor-link heading3"><div>什么是自旋锁？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#什么是锁消除" class="anchor-link heading3"><div>什么是锁消除？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#什么是锁粗化" class="anchor-link heading3"><div>什么是锁粗化？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#什么是轻量级锁" class="anchor-link heading3"><div>什么是轻量级锁？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#什么是偏向锁" class="anchor-link heading3"><div>什么是偏向锁？</div></a></li><li class="anchor"><a href="/interview/java-multithread/lock/#在-java-中怎么排查死锁" class="anchor-link heading2"><div>在 Java 中怎么排查死锁？</div></a></li></ul></div></aside></div> <!----> <div class="content__content-top"></div> <div class="theme-default-content content__default"><h2 id="什么是互斥同步"><a href="#什么是互斥同步" class="header-anchor">#</a> 什么是互斥同步？</h2> <p>互斥同步属于一种悲观的并发策略，总是认为只要不去做正确的同步措施，那就肯定会出现问题。无论共享数据是否真的会出现竞争，它都要进行加锁（这里讨论的是概念模型，实际上虚拟机会优化掉很大一部分不必要的加锁，下面会提到）。互斥同步最主要的问题就是线程阻塞和唤醒所带来的性能问题，因此这种同步也称为阻塞同步。</p> <h2 id="介绍一下-synchronized-关键字"><a href="#介绍一下-synchronized-关键字" class="header-anchor">#</a> 介绍一下 Synchronized 关键字？<span class="badge error" style="vertical-align:top;" data-v-7b453e57>重点</span></h2> <p><code>synchronized</code> 关键字可用于：</p> <ul><li>同步一个代码块</li> <li>同步一个方法（可以为静态方法）</li> <li>同步一个类</li></ul> <p><code>synchronized</code> 可以保证可见性，因为：</p> <ul><li>线程加锁前，会清空工作内存中共享变量的值，从而使用共享变量时需要从主内存中重新读取最新的值</li> <li>线程解锁前，必须把共享变量的最新值刷新到主内存中</li></ul> <div class="custom-block tip"><p class="custom-block-title">synchronized 在字节码中的实现</p> <ul><li>同步代码块时使用 <code>monitorenter</code> 和 <code>monitorexit</code> 指令，其中 <code>monitorenter</code> 指令指向同步代码块的开始位置，<code>monitorexit</code> 指令则指明同步代码块的结束位置</li> <li>同步方法时并没有 <code>monitorenter</code> 指令和 <code>monitorexit</code> 指令，取得代之的是使用 <code>ACC_SYNCHRONIZED</code> 标识，该标识指明了该方法是一个同步方法</li></ul></div> <div class="custom-block tip"><p class="custom-block-title">Mark Word</p> <p>在 JVM 中对象是分成三部分存在的：对象头（header）、实例数据（instance Data）、对齐填充（padding）。实例数据存放类的属性数据信息，包括父类的属性信息，如果是数组，那么实例部分还包括数组的长度，这部分内存按 4 字节对齐。对齐填充不是必须部分，由于虚拟机要求对象起始地址必须是 8 字节的整数倍，对齐填充仅仅是为了使字节对齐。</p> <p>对象头是 <code>synchronized</code> 实现锁的基础，因为 <code>synchronized</code> 申请锁、上锁、释放锁都与对象头有关。对象头主要结构是由 Mark Word 和 Class Metadata Address 组成的，其中 Mark Word 存储对象的哈希值、锁信息、分代年龄、GC 标志等信息，Class Metadata Address 是类型指针指向对象的类元数据，JVM 通过该指针确定该对象是哪个类的实例。</p> <p>其中 Mark Word 的锁信息就体现了锁的状态：</p> <ul><li>无锁</li> <li>偏向锁：多数情况下，锁不仅不存在竞争，而且总是由同一线程多次获得，为了让线程获得锁的代价更低而引入了偏向锁，见锁优化部分的第五点</li> <li>轻量级锁：如果明显存在其他线程申请锁，那么偏向锁将很快升级为轻量级锁</li> <li>重量级锁：指原始的 <code>synchronized</code> 的实现，其他线程试图获取锁时都会被阻塞，只有持有锁的线程释放锁之后才会唤醒这些线程</li></ul></div> <h2 id="介绍一下-reentrantlock-类"><a href="#介绍一下-reentrantlock-类" class="header-anchor">#</a> 介绍一下 ReentrantLock 类？</h2> <p><code>ReentrantLock</code> 是 J.U.C 包中提供的锁。示例代码如下：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Main</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">Lock</span> lock <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ReentrantLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">ExecutorService</span> executorService <span class="token operator">=</span> <span class="token class-name">Executors</span><span class="token punctuation">.</span><span class="token function">newCachedThreadPool</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        executorService<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token class-name">Main</span><span class="token operator">::</span><span class="token function">func</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        executorService<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token class-name">Main</span><span class="token operator">::</span><span class="token function">func</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        executorService<span class="token punctuation">.</span><span class="token function">shutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        lock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>i <span class="token operator">+</span> <span class="token string">&quot; &quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
            lock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><h2 id="它们两个有什么区别"><a href="#它们两个有什么区别" class="header-anchor">#</a> 它们两个有什么区别？<span class="badge error" style="vertical-align:top;" data-v-7b453e57>重点</span></h2> <p>这个问题可以泛指为 <code>synchronized</code> 和 <code>Lock</code> 接口的区别。</p> <ul><li>锁的实现：<code>synchronized</code> 是 JVM 实现，<code>ReentrantLock</code> 是 JDK 实现的</li> <li>性能： Java 对 <code>synchronized</code> 进行了很多优化，例如自旋锁等，<code>synchronized</code> 与 <code>ReentrantLock</code> 的性能大致相同</li> <li>等待可中断： 当持有锁的线程长期不释放锁的时候，正在等待的线程可以选择放弃等待，改为处理其他事情。<code>ReentrantLock</code> 可中断，而 <code>synchronized</code> 不行</li> <li>公平锁：<code>synchronized</code> 中的锁是非公平的，<code>ReentrantLock</code> 默认情况下也是非公平的，但是也可以是公平的</li> <li>锁的绑定条件：一个 <code>ReentrantLock</code> 可以同时绑定多个 <code>Condition</code> 对象，所以它更为灵活</li></ul> <div class="custom-block tip"><p class="custom-block-title">锁的使用</p> <p>除非需要使用 <code>ReentrantLock</code> 的高级功能，否则优先使用 <code>synchronized</code>。这是因为 <code>synchronized</code> 是 JVM 实现的一种锁机制，JVM 原生地支持它，而 <code>ReentrantLock</code> 不是所有的 JDK 版本都支持。并且使用 <code>synchronized</code> 不用担心没有释放锁而导致死锁问题，因为 JVM 会确保锁的释放。</p></div> <h2 id="什么是非阻塞同步"><a href="#什么是非阻塞同步" class="header-anchor">#</a> 什么是非阻塞同步？</h2> <p>与悲观策略不同，还可以使用一种基于冲突检测的乐观并发策略：先进行操作，如果没有其它线程争用共享数据，那操作就成功了，否则采取补偿措施（不断地重试，直到成功为止）。这种乐观的并发策略的许多实现都不需要将线程阻塞，因此这种同步操作称为非阻塞同步，即乐观锁。</p> <h2 id="什么是-cas"><a href="#什么是-cas" class="header-anchor">#</a> 什么是 CAS？<span class="badge error" style="vertical-align:top;" data-v-7b453e57>重点</span></h2> <p>乐观锁需要操作和冲突检测这两个步骤具备原子性，这里就不能再使用互斥同步来保证了，只能靠硬件来完成。硬件支持的原子性操作最典型的是：比较并交换（Compare-and-Swap，CAS）。CAS 指令需要有 3 个操作数，分别是内存地址 V、旧的预期值 A 和新值 B。当执行操作时，只有当 V 的值等于 A，才将 V 的值更新为 B。</p> <div class="custom-block tip"><p class="custom-block-title">Unsafe 类</p> <p>有关 CAS 的操作可以在 <code>Unsafe</code> 类中查看，CAS 在不能成功交换时会进行自旋。</p></div> <h2 id="cas-存在的问题"><a href="#cas-存在的问题" class="header-anchor">#</a> CAS 存在的问题？<span class="badge error" style="vertical-align:top;" data-v-7b453e57>重点</span></h2> <h3 id="aba-问题"><a href="#aba-问题" class="header-anchor">#</a> ABA 问题</h3> <p>如果一个变量初次读取的时候是 A，它的值被改成了 B，后来又被改回为 A，那 CAS 操作就会误认为它从来没有被改变过。J.U.C 包提供了一个带有标记的原子引用类 <code>AtomicStampedReference</code> 来解决这个问题，它可以通过控制变量值的版本来保证 CAS 的正确性。大部分情况下 ABA 问题不会影响程序并发的正确性，如果需要解决 ABA 问题，改用传统的互斥同步可能会比原子类更高效。</p> <h3 id="自旋消耗资源"><a href="#自旋消耗资源" class="header-anchor">#</a> 自旋消耗资源</h3> <p>CAS 如果长时间不成功，会给CPU带来非常大的执行开销，如果 JVM 能支持处理器提供的 <code>pause</code> 指令，那么效率会有一定的提升。<code>pause</code> 指令有两个作用：</p> <ul><li>它可以延迟流水线执行指令（de-pipeline），使 CPU 不会消耗过多的执行资源，延迟的时间取决于具体实现的版本，在一些处理器上延迟时间是零</li> <li>它可以避免在循环的时候因内存顺序冲突（Memory Order Violation）而引起 CPU 流水线被清空，从而提高 CPU 的实行效率</li></ul> <h3 id="多变量共享一致性问题"><a href="#多变量共享一致性问题" class="header-anchor">#</a> 多变量共享一致性问题</h3> <p>CAS 操作是针对一个变量的，如果对多个变量操作：</p> <ul><li>可以加锁</li> <li>封装成对象类</li></ul> <h2 id="介绍一下-atomicinteger-类"><a href="#介绍一下-atomicinteger-类" class="header-anchor">#</a> 介绍一下 AtomicInteger 类？</h2> <p>J.U.C 包里面的整数原子类 <code>AtomicInteger</code> 的方法调用了 <code>Unsafe</code> 类的 CAS 操作来保证线程安全。示例代码如下：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">AtomicInteger</span> value <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AtomicInteger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">int</span> total <span class="token operator">=</span> <span class="token number">1000</span><span class="token punctuation">;</span>
    <span class="token class-name">ExecutorService</span> executorService <span class="token operator">=</span> <span class="token class-name">Executors</span><span class="token punctuation">.</span><span class="token function">newCachedThreadPool</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">CountDownLatch</span> countDownLatch <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CountDownLatch</span><span class="token punctuation">(</span>total<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> total<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        executorService<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span> <span class="token punctuation">{</span>
            value<span class="token punctuation">.</span><span class="token function">incrementAndGet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            countDownLatch<span class="token punctuation">.</span><span class="token function">countDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    executorService<span class="token punctuation">.</span><span class="token function">shutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">try</span> <span class="token punctuation">{</span>
        countDownLatch<span class="token punctuation">.</span><span class="token function">await</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>value<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><p><code>incrementAndGet()</code> 会调用 <code>Unsafe</code> 包中的 <code>getAndAddInt</code>，其中：</p> <ul><li><code>var1</code> 为原子类对象</li> <li><code>var2</code> 为该字段相对对象内存地址的偏移</li> <li><code>var4</code> 为要增加的数值，这里为 1</li> <li><code>var5</code> 为旧的预期值</li></ul> <p>通过 <code>compareAndSwapInt</code> 进行比较并交换，如果失败会一直自旋。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token function">getAndAddInt</span><span class="token punctuation">(</span><span class="token class-name">Object</span> var1<span class="token punctuation">,</span> <span class="token keyword">long</span> var2<span class="token punctuation">,</span> <span class="token keyword">int</span> var4<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">int</span> var5<span class="token punctuation">;</span>
    <span class="token keyword">do</span> <span class="token punctuation">{</span>
        var5 <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getIntVolatile</span><span class="token punctuation">(</span>var1<span class="token punctuation">,</span> var2<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">compareAndSwapInt</span><span class="token punctuation">(</span>var1<span class="token punctuation">,</span> var2<span class="token punctuation">,</span> var5<span class="token punctuation">,</span> var5 <span class="token operator">+</span> var4<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> var5<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h2 id="锁优化"><a href="#锁优化" class="header-anchor">#</a> 锁优化 <span class="badge error" style="vertical-align:top;" data-v-7b453e57>重点</span></h2> <h3 id="什么是自旋锁"><a href="#什么是自旋锁" class="header-anchor">#</a> 什么是自旋锁？</h3> <p>互斥同步进入阻塞状态的开销都很大，应该尽量避免。在许多应用中，共享数据的锁定状态只会持续很短的一段时间。自旋锁的思想是让一个线程在请求一个共享数据的锁时执行忙循环（自旋）一段时间，如果在这段时间内能获得锁，就可以避免进入阻塞状态。</p> <p>自旋锁虽然能避免进入阻塞状态从而减少开销，但是它需要进行忙循环操作占用 CPU 时间，它只适用于共享数据的锁定状态很短的场景。在 JDK 1.6 中引入了自适应的自旋锁。自适应意味着自旋的次数不再固定了，而是由前一次在同一个锁上的自旋次数及锁的拥有者的状态来决定。</p> <h3 id="什么是锁消除"><a href="#什么是锁消除" class="header-anchor">#</a> 什么是锁消除？</h3> <p>锁消除是指对于被检测出不可能存在竞争的共享数据的锁进行消除。锁消除主要是通过逃逸分析来支持，如果堆上的共享数据不可能逃逸出去被其它线程访问到，那么就可以把它们当成私有数据对待，也就可以将它们的锁进行消除。</p> <h3 id="什么是锁粗化"><a href="#什么是锁粗化" class="header-anchor">#</a> 什么是锁粗化？</h3> <p>如果一系列的连续操作都对同一个对象反复加锁和解锁，频繁的加锁操作就会导致性能损耗。如果虚拟机探测到有这样的一串零碎的操作都对同一个对象加锁，将会把加锁的范围扩展（粗化）到整个操作序列的外部，减少加锁的次数。</p> <h3 id="什么是轻量级锁"><a href="#什么是轻量级锁" class="header-anchor">#</a> 什么是轻量级锁？</h3> <p>轻量级锁是相对于传统的重量级锁而言，它使用 CAS 操作来避免重量级锁使用互斥量的开销。对于绝大部分的锁，在整个同步周期内都是不存在竞争的，因此也就不需要都使用互斥量进行同步，可以先采用 CAS 操作进行同步，如果 CAS 失败了再改用互斥量进行同步。</p> <h3 id="什么是偏向锁"><a href="#什么是偏向锁" class="header-anchor">#</a> 什么是偏向锁？</h3> <p>偏向锁的思想是：偏向于第一个获取锁对象的线程，这个线程在之后获取该锁时就不再需要进行同步操作，甚至连 CAS 操作也不再需要。当锁对象第一次被线程获得的时候，进入偏向状态，如果 CAS 操作成功，这个线程以后每次进入这个锁相关的同步块就不需要再进行任何同步操作。但是只要有另外一个线程去尝试获取这个锁对象时，偏向状态就宣告结束，此时会撤销偏向后恢复到未锁定状态或者轻量级锁状态。</p> <h2 id="在-java-中怎么排查死锁"><a href="#在-java-中怎么排查死锁" class="header-anchor">#</a> 在 Java 中怎么排查死锁？</h2> <p>首先模拟一下死锁：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Main</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token class-name">A</span><span class="token operator">::</span><span class="token function">method</span><span class="token punctuation">,</span> <span class="token string">&quot;Thread A&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token class-name">B</span><span class="token operator">::</span><span class="token function">method</span><span class="token punctuation">,</span> <span class="token string">&quot;Thread B&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">A</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">synchronized</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">method</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">&quot;: method from A&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">B</span><span class="token punctuation">.</span><span class="token function">method</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">B</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">synchronized</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">method</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">&quot;: method from B&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">A</span><span class="token punctuation">.</span><span class="token function">method</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><p>线程 A 首先调用了 A 类中的同步方法，休眠 3 秒再继续调用 B 类中的同步方法。但是 B 类中的同步方法已经被线程 B 所调用，而线程 B 正在等待调用线程 A 的同步方法，所以双方会死锁。执行代码后将只会得到：</p> <div class="language-text line-numbers-mode"><pre class="language-text"><code>Thread A: method from A 
Thread B: method from B
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>可以使用 <code>jstack -l &lt;pid&gt;</code> 命令查看线程信息：</p> <div class="language-text line-numbers-mode"><pre class="language-text"><code>&quot;Thread A&quot; #11 prio=5 os_prio=0 tid=0x000000001e899800 nid=0x32c4 waiting for monitor entry [0x000000001f3af000] 
   java.lang.Thread.State: BLOCKED (on object monitor) 
        at xyz.lixiangyu.demo.B.method(Main.java:25) 
        - waiting to lock &amp;lt;0x000000076b61f5f0&gt; (a java.lang.Class for xyz.lixiangyu.demo.B) 
        at xyz.lixiangyu.demo.A.method(Main.java:16) 
        - locked &amp;lt;0x000000076b3a45c0&gt; (a java.lang.Class for xyz.lixiangyu.demo.A) 
        at xyz.lixiangyu.demo.Main$$Lambda$1/1174361318.run(Unknown Source) 
        at java.lang.Thread.run(Thread.java:748) 
 
   Locked ownable synchronizers: 
        - None
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>另外在 <code>jstack</code> 命令的输出中可以看到 Java 已经分析到了出现了死锁：</p> <div class="language-text line-numbers-mode"><pre class="language-text"><code>Found one Java-level deadlock: 
============================= 
&quot;Thread B&quot;: 
  waiting to lock monitor 0x000000001c5025d8 (object 0x000000076b3a45c0, a java.lang.Class), 
  which is held by &quot;Thread A&quot; 
&quot;Thread A&quot;: 
  waiting to lock monitor 0x000000001c4ffd48 (object 0x000000076b61f5f0, a java.lang.Class), 
  which is held by &quot;Thread B&quot;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div></div> <!----> <div class="content__content-bottom"></div> <footer class="page-meta"><div class="edit-link"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon edit-icon"><path d="M117.953 696.992 64.306 959.696l265.931-49.336 450.204-452.505-212.284-213.376-450.204 452.513zm496.384-296.326L219.039 797.993l-46.108-46.34L568.233 354.33l46.104 46.335zm345.357-122.99-114.45 115.04-212.288-213.377 114.45-115.035 212.288 213.371zm0 0" fill="currentColor"></path></svg> <a href="https://github.com/lxy1152/lxy1152.github.io/edit/main/interview/java-multithread/lock.md" target="_blank" rel="noopener noreferrer">编辑此页</a></div> <div class="meta-item update-time"><span class="label">上次编辑于:</span> <span class="info">2021年8月1日 19:23</span></div> <div class="meta-item contributors"><span class="label">贡献者: </span> <span class="info"><span title="email: 2676092082@qq.com" class="contributor">
          Xiangyu Li
        </span> <!----></span></div></footer> <div class="page-nav"><p class="inner"><span class="prev"><a href="/interview/java-multithread/juc/" class="prev"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon prev-icon"><path d="M906.783 588.79c-.02 8.499-6.882 15.36-15.38 15.37l-443.7-.01 75.704 191.682c2.52 6.42.482 13.763-5.038 17.91-5.52 4.168-13.138 4.147-18.616-.092L123.228 524.175a15.362 15.362 0 0 1-6-12.165c0-4.782 2.222-9.277 6-12.185L499.753 210.35a15.388 15.388 0 0 1 9.38-3.195c3.236 0 6.502 1.034 9.236 3.103 5.52 4.147 7.578 11.49 5.038 17.91L447.683 419.84l443.72-.01c8.498.01 15.36 6.881 15.36 15.36l.02 153.6z" fill="currentColor"></path></svg>
        🐵 J.U.C
      </a></span> <span class="next"><a href="/interview/java-multithread/non-lock/">
        🦍 无同步方案
        <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon next-icon"><path d="M906.772 512c0 4.772-2.211 9.267-5.99 12.175L524.257 813.66a15.37 15.37 0 0 1-18.616.092 15.368 15.368 0 0 1-5.038-17.91l75.714-191.672h-443.73c-8.488 0-15.36-6.881-15.36-15.36v-153.6c0-8.489 6.872-15.36 15.36-15.36h443.73l-75.714-191.682a15.358 15.358 0 0 1 5.048-17.91c5.51-4.158 13.128-4.137 18.606.092l376.525 289.485a15.323 15.323 0 0 1 5.99 12.165z" fill="currentColor"></path></svg></a></span></p></div> <div class="comments-wrapper"><div class="waline-wrapper"><div id="waline-comment"></div></div></div> <!----> <div class="content__page-bottom"></div></main> <footer class="footer-wrapper"><!----> <!----> <div class="copyright">Copyright © 2021 Xiangyu Li</div></footer></div><div class="global-ui"><!----><div tabindex="-1" role="dialog" aria-hidden="true" class="pswp"><div class="pswp__bg"></div> <div class="pswp__scroll-wrap"><div class="pswp__container"><div class="pswp__item"></div> <div class="pswp__item"></div> <div class="pswp__item"></div></div> <div class="pswp__ui pswp__ui--hidden"><div class="pswp__top-bar"><div class="pswp__counter"></div> <button class="pswp__button pswp__button--close"></button> <button class="pswp__button pswp__button--share"></button> <button class="pswp__button pswp__button--fs"></button> <button class="pswp__button pswp__button--zoom"></button> <div class="pswp__preloader"><div class="pswp__preloader__icn"><div class="pswp__preloader__cut"><div class="pswp__preloader__donut"></div></div></div></div></div> <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"><div class="pswp__share-tooltip"></div></div> <button class="pswp__button pswp__button--arrow--left"></button> <button class="pswp__button pswp__button--arrow--right"></button> <div class="pswp__caption"><div class="pswp__caption__center"></div></div></div></div></div></div></div>
    <script src="/assets/js/app.a42375e9.js" defer></script><script src="/assets/js/vendors~layout-Layout.8269724e.js" defer></script><script src="/assets/js/vendors~layout-Blog~layout-Layout~layout-NotFound.43b0f70d.js" defer></script><script src="/assets/js/page-🐒锁.868714d5.js" defer></script><script src="/assets/js/vendors~layout-Blog~layout-Layout~layout-NotFound~layout-Slide.99c28334.js" defer></script>
  </body>
</html>
